﻿#include "StdAfx.h"

namespace DuiLib {

    CDelegateBase::CDelegateBase(void *pObject, void *pFn) {
        m_pObject = pObject;
        m_pFn = pFn;
    }

    CDelegateBase::CDelegateBase(const CDelegateBase &rhs) {
        m_pObject = rhs.m_pObject;
        m_pFn = rhs.m_pFn;
    }

    CDelegateBase::~CDelegateBase() {

    }

    bool CDelegateBase::Equals(const CDelegateBase &rhs) const {
        return m_pObject == rhs.m_pObject && m_pFn == rhs.m_pFn;
    }

    bool CDelegateBase::operator() (void *param) {
        return Invoke(param);
    }

    void *CDelegateBase::GetFn() {
        return m_pFn;
    }

    void *CDelegateBase::GetObject() {
        return m_pObject;
    }

    CEventSource::~CEventSource() {
        for( int i = 0; i < m_aDelegates.GetSize(); i++ ) {
            CDelegateBase *pObject = static_cast<CDelegateBase *>(m_aDelegates[i]);

            if( pObject) delete pObject;
        }
    }

    CEventSource::operator bool() {
        return m_aDelegates.GetSize() > 0;
    }

    void CEventSource::operator+= (const CDelegateBase &d) {
        for( int i = 0; i < m_aDelegates.GetSize(); i++ ) {
            CDelegateBase *pObject = static_cast<CDelegateBase *>(m_aDelegates[i]);

            if( pObject && pObject->Equals(d) ) return;
        }

        m_aDelegates.Add(d.Copy());
    }

    void CEventSource::operator+= (FnType pFn) {
        (*this) += MakeDelegate(pFn);
    }

    void CEventSource::operator-= (const CDelegateBase &d) {
        for( int i = 0; i < m_aDelegates.GetSize(); i++ ) {
            CDelegateBase *pObject = static_cast<CDelegateBase *>(m_aDelegates[i]);

            if( pObject && pObject->Equals(d) ) {
                delete pObject;
                m_aDelegates.Remove(i);
                return;
            }
        }
    }

    void CEventSource::operator-= (FnType pFn) {
        (*this) -= MakeDelegate(pFn);
    }

    bool CEventSource::operator() (void *param) {
        bool ret = true;
        for( int i = 0; i < m_aDelegates.GetSize(); i++ ) {
            CDelegateBase *pObject = static_cast<CDelegateBase *>(m_aDelegates[i]);
            if (pObject) {
                if (!(*pObject)(param)) {
                    ret = false;
                }
            }
        }

        return ret;
    }

    void CEventSource::Clear() {
        for( int i = 0; i < m_aDelegates.GetSize(); i++ ) {
            CDelegateBase *pObject = static_cast<CDelegateBase *>(m_aDelegates[i]);

            if( pObject) delete pObject;
        }

        m_aDelegates.Empty();
    }
} // namespace DuiLib
